package com.gl.battleship.services.managers;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.gl.battleship.domain.Game;
import com.gl.battleship.domain.Notification;
import com.gl.battleship.domain.NotificationType;
import com.gl.battleship.domain.Player;
import com.gl.battleship.domain.User;
import com.gl.battleship.dto.PositionDto;
import com.gl.battleship.services.exceptions.MessagesExceptions;
import com.gl.battleship.services.exceptions.NotificationException;
import com.gl.battleship.services.exceptions.UserException;

@Service
@Scope("singleton")
public class NotificationManager  {

	public static Set <Notification> notifications = new HashSet<Notification>();
	

	/**
	 * list the users notifications 
	 * 
	 * @param nick is the nick user
	 * @return the list notifications users
	 * @throws UserException 
	 * @throws NotificationException 
	 */
	public static List<Notification>listNotification(String nick) throws UserException, NotificationException{
		List<Notification> listNotification=new ArrayList<Notification>();;	
		
		Iterator <Notification> it = notifications.iterator();
		while (it.hasNext()) {
			Notification notification = it.next();
			if (notification.getUser().getNick().equals(nick))
			{
				listNotification.add(notification);
				}
							
		}
		if(listNotification.size()==0){
			throw new NotificationException(MessagesExceptions.INVALID_USER);
		}else
			return 	listNotification;
		
	}
	
	
	/**
	 * Remove the specific notification 
	 * 
	 * @param wartoken is an String that identified the war
	 * @param notificationType is an Constant that defined the notification Type:'DECLARED_WAR','ACCEPTED_WAR','REFUSED_WAR','RETIRED_WAR','TURN_TO_SHOOT'.
	 */
	public static void  removeNotification(String wartoken,NotificationType notificationType){
		Iterator<Notification> it = notifications.iterator();
		Notification notificationsToRemove=new Notification();
			
		while (it.hasNext()) {
			Notification notification = (Notification)it.next();
			
			if ((notification.getGame().getWarkToken().equals(wartoken))&&(notification.getTypeNotification().equals(notificationType)))
			{
				notificationsToRemove=notification;
				
				}				
			}
		notifications.remove(notificationsToRemove);
		
		}
	
		
	/**
	 * Remove an notification of an user
	 * 
	 * @param nick is the user nick
	 */
	public static void removeNotificationByNick(String nick){
		Iterator <Notification>it = notifications.iterator();
		List<Notification> notificationsToRemove=new ArrayList<Notification>();
		while (it.hasNext()) {
			Notification notification = (Notification) it.next();
			if ((notification.getUser().getNick().equals(nick)))
			{
				it.remove();
				notificationsToRemove.add(notification);
				}			
		}
		
		notifications.removeAll(notificationsToRemove);		
		
	}
	/**
	 * Remove all the old notifications declared by the participants and the made by others to them
	 * 
	 * @param game
	 * @param notificationType
	 * @return
	 */
	
	
	
	public static void removeNotifications(Game game,NotificationType notificationType){
		Iterator <Notification>it = notifications.iterator();
		List<Notification> notificationsToRemove=new ArrayList<Notification>();
		synchronized (notifications) {
			while (it.hasNext()) {
			Notification notification = (Notification) it.next();
			if (((notification.getGame().getPlayerOne().getUser().getNick()).equals(game.getPlayerOne().getUser().getNick()) ||
				(notification.getGame().getPlayerTwo().getUser().getNick()).equals(game.getPlayerOne().getUser().getNick())
				||(notification.getGame().getPlayerTwo().getUser().getNick()).equals(game.getPlayerTwo().getUser().getNick())||
				(notification.getGame().getPlayerOne().getUser().getNick()).equals(game.getPlayerTwo().getUser().getNick()))
				&& (notification.getTypeNotification().equals(notificationType)))
			{
				notificationsToRemove.add(notification);
				}			
		}
		}
		notifications.removeAll(notificationsToRemove);		
		
	}
	
	public static void addNotificationTurnShoot(Notification notification){
		Iterator<Notification> it = notifications.iterator();
		boolean band = true;
		Notification notification2 = null;
		while (it.hasNext()) {
			Notification e = (Notification) it.next();
			if (e.getTypeNotification().equals(notification.getTypeNotification()) && 
				e.getGame().getWarkToken().equals(notification.getGame().getWarkToken()) ){
				notification2 = e;
				band = false;
			}
			
		}
		if(!band){
			notifications.remove(notification2);
		}
		notifications.add(notification);
	}
	
	public static void addNotificationShoots(Game game, NotificationType notificationType, PositionDto positionDto, Player player){
		Boolean band = true;
		Notification notification2 = null;
		Iterator<Notification> it = notifications.iterator();
		while (it.hasNext()) {
			Notification e = (Notification) it.next();
			if (e.getTypeNotification().equals(notificationType) && e.getGame().getWarkToken().equals(game.getWarkToken()) && 
				e.getUser().getNick().equals(player.getUser().getNick())){
				
				for(PositionDto positionDtos: e.getShoots()){
					if(positionDtos.getX() == positionDto.getX() && positionDtos.getY().equals(positionDto.getY())){
						band = false;
						return;
					}else{
						notification2 = e;
					}
				}
				band = false;
			}
		}
		
		if(!band){
			notification2.getShoots().add(positionDto);
		}else{
			Notification notification = new Notification();
			notification.setGame(game);
			List< PositionDto> shoots = new ArrayList<PositionDto>();
			shoots.add(positionDto);
			notification.setShoots(shoots);
			notification.setTypeNotification(notificationType);
			notification.setUser(player.getUser());
			notifications.add(notification);
		}
		

	}
	
	public static List<Notification>listNotificationState(String nick, String state) throws UserException{
		List<Notification> listNotification=new ArrayList<Notification>();;	
		
		Iterator <Notification> it = notifications.iterator();
		while (it.hasNext()) {
			Notification notification = it.next();
			if (notification.getUser().getNick().equals(nick)&& notification.getTypeNotification().toString().equals(state))
			{
				listNotification.add(notification);
			}
							
		}

	return 	listNotification;
		
	}
	
	
	
	
}
